package core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import agency.Refunds;
import common.Sequence;
import common.Service;
import common.Servlet;
import common.Validate;
import dict.BcDict;
import dict.CbDict;
import dict.CommonDict;
import dict.TransactionDict;
import dicts.GlobalDict;
import dicts.PaymentDict;
import entities.TBank;
import entities.TBc;
import entities.TCard;
import entities.TCb;
import entities.TMerchant;
import entities.TMs;
import entities.TSc;
import entities.TSm;
import entities.TTransaction;
import interfaces.IBankService;
import interfaces.IBcService;
import interfaces.ICardService;
import interfaces.ICbService;
import interfaces.IMerchantService;
import interfaces.IMsService;
import interfaces.IScService;
import interfaces.ISmService;
import interfaces.ITransactionService;
import net.sf.json.JSONObject;
import util.LogUtil;
import utils.DateUtil;
import utils.NumberUtil;
import utils.StringUtil;

public class Return extends Servlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public synchronized void process(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(DateUtil.format(new Date(), DateUtil.DATETIME) + " | 退款退回");

		// 初始化service
		IBankService bankService = (IBankService) Service.create(IBankService.class);
		ITransactionService transactionService = (ITransactionService) Service.create(ITransactionService.class);
		IMerchantService merchantService = (IMerchantService) Service.create(IMerchantService.class);
		ICardService cardService = (ICardService) Service.create(ICardService.class);
		IBcService bcService = (IBcService) Service.create(IBcService.class);
		ICbService cbService = (ICbService) Service.create(ICbService.class);
		IScService scService = (IScService) Service.create(IScService.class);
		ISmService smService = (ISmService) Service.create(ISmService.class);
		IMsService msService = (IMsService) Service.create(IMsService.class);

		Map<String, Object> paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
		JSONObject jsonResult = new JSONObject();

		// 初始化bean和属性
		TBank bank = new TBank();
		TMerchant merchant = new TMerchant();
		TCard card = new TCard();
		TTransaction transaction = new TTransaction();
		TBc bc = new TBc();
		TCb cb = new TCb();
		TSc sc = new TSc();
		TSm sm = new TSm();
		TMs ms = new TMs();

		// 验证系统
		if (GlobalDict.LINUX.equalsIgnoreCase(System.getProperty("os.name")) && !CommonDict.HOST.equals(request.getServerName())) {
			response.getWriter().print(Validate.result(TransactionDict.ILLAGEL_ACCESS, TransactionDict.MESSAGES.get(TransactionDict.ILLAGEL_ACCESS)));
			return;
		}

		// 校验参数 ( 名称,值,校验模式,边界 )
		List<Object[]> parameterList = Collections.synchronizedList(new ArrayList<Object[]>());
		parameterList.add(new Object[] { "cbNo", request.getParameter("cbNo"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });

		JSONObject validateResult = Validate.validate(parameterList);
		LogUtil.retun(Validate.summary(parameterList));

		if (!StringUtil.isEmpty(validateResult)) {
			System.out.println ( validateResult.toString() ) ;
			response.getWriter().print(validateResult.toString());
			return;
		}

		// 出账存在状态
		try {
			cb = cbService.fetch(request.getParameter("cbNo"));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(CbDict.CB_FETCH_EXCEPTION, CbDict.MESSAGES.get(CbDict.CB_FETCH_EXCEPTION)));
			return;
		}
		if (cb == null) {
			response.getWriter().print(Validate.result(CbDict.CB_NOT_EXIST, CbDict.MESSAGES.get(CbDict.CB_NOT_EXIST)));
			return;
		}

		if (!cb.getCbState().equals("0")) {
			response.getWriter().print(Validate.result(CbDict.CB_STATUS_EXCEPTION, CbDict.MESSAGES.get(CbDict.CB_STATUS_EXCEPTION)));
			return;
		}

		// 入账存在状态
		try {
			bc = bcService.fetch(cb.getCbOrder());
		} catch (Exception e) {
			e.printStackTrace();
			response.getWriter().print(Validate.result(BcDict.BC_FETCH_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_FETCH_EXCEPTION)));
			return;
		}

		if (bc == null) {
			response.getWriter().print(Validate.result(BcDict.BC_NOT_EXIST, BcDict.MESSAGES.get(BcDict.BC_NOT_EXIST)));
			return;
		}

		if (!bc.getBcState().equals("1")) {
			response.getWriter().print(Validate.result(BcDict.BC_STATUS_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_STATUS_EXCEPTION)));
			return;
		}

		//查出对应交易
		try {
			transaction = transactionService.fetch(cb.getTxnNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_FETCH_EXCEPTION)));
			return;
		}
		if (transaction == null) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_NOT_EXIST)));
			return;
		}
		if (!transaction.getTxnState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_STATUS_EXCEPTION)));
			return;
		}
		
		//查出对应商户
		try {
			merchant = merchantService.fetch(transaction.getMerNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_FETCH_EXCEPTION)));
			return;
		}
		if (merchant == null) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_NOT_EXIST)));
			return;
		}
		if (!merchant.getMerState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_STATUS_EXCEPTION)));
			return;
		}
		
		//查出对应持卡人
		try {
			card = cardService.fetch(transaction.getCrdNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CARD_FETCH_EXCEPTION)));
			return;
		}
		if (card == null) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.CARD_NOT_EXIST)));
			return;
		}
		if (!card.getCrdState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CARD_STATUS_EXCEPTION)));
			return;
		}

		try {
			bank = bankService.fetch(cb.getBnkNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_FETCH_EXCEPTION)));
			return;
		}
		if (bank == null) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION)));
			return;
		}
		if (!bank.getBnkState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CLOSED, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CLOSED)));
			return;
		}
		
		// 计算退款金额
		try {
			ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(cb.getCbAmount(), bc.getBcAmount(), 8)));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.CALCULATE_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CALCULATE_EXCEPTION)));
			return;
		}

		// 退款金额大于剩余金额
		if (ms.getMsAmount() > transaction.getTxnRemain()) {
			response.getWriter().print(Validate.result(TransactionDict.REFUND_AMOUNT_GREATER_THAN_REMAINING, TransactionDict.MESSAGES.get(TransactionDict.REFUND_AMOUNT_GREATER_THAN_REMAINING)));
			return;
		}

		// 把退款交易送往对应收单行
		try {
			((Refunds) Class.forName("agency.refunds." + StringUtil.upperHead(bank.getBnkNo().substring(0, 6).toLowerCase())).newInstance()).process(cb, transaction, bank, card);
			cbService.persist(cb);
		} catch (Exception e) {
			e.printStackTrace ( );
			response.getWriter().print(Validate.result(CbDict.CB_PROCESS_EXCEPTION, CbDict.MESSAGES.get(CbDict.CB_PROCESS_EXCEPTION)));
			return;
		}

		// 提交上游处理完成后根据退款状态进行清结算
		if (cb.getCbState().equals("1")) {
			ms.setMsNo(Sequence.msSequence());
			ms.setMerNo(merchant.getMerNo());
			ms.setTxnNo(transaction.getTxnNo());
			ms.setMsType(PaymentDict.MS_REFUND);
			ms.setMsAmount(ms.getMsAmount());
			ms.setMsState("1");
			ms.setMsDate(new Date());
			ms.setMsRemark(cb.getCbRemark());
			msService.persist(ms);

			sc.setScNo(Sequence.scSequence());
			sc.setCrdNo(transaction.getCrdNo());
			sc.setTxnNo(transaction.getTxnNo());
			sc.setScType(PaymentDict.SC_DEALAGE);
			sc.setScAmount(ms.getMsAmount());
			sc.setScState("1");
			sc.setScDate(new Date());
			scService.persist(sc);

			sc.setScNo(Sequence.scSequence());
			sc.setCrdNo(transaction.getCrdNo());
			sc.setTxnNo(transaction.getTxnNo());
			sc.setScType(PaymentDict.SC_MARKUP);
			sc.setScAmount(NumberUtil.sub(cb.getCbAmount(), ms.getMsAmount()));
			sc.setScState("1");
			sc.setScDate(new Date());
			scService.persist(sc);
			
			transaction.setTxnRemain(NumberUtil.sub(transaction.getTxnRemain(), ms.getMsAmount()));
			if (transaction.getTxnRemain() == 0) {
				transaction.setTxnLogic("1");
			}
			transaction.setTxnRefund("1");
			transactionService.persist(transaction);

			// 时间小于24小时,并且商户配置为退还手续费
			if (merchant.getMerRefunding().equals("1") && new Date().getTime() - transaction.getTxnDate().getTime() < GlobalDict.DAY) {
				try {
					paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
					paramMap.put("txnNo", StringUtil.split(request.getParameter("transaction")));
					paramMap.put("msType", PaymentDict.MS_POUNDAGE);
					ms = msService.single(paramMap);
				} catch (Exception e) {
					response.getWriter().print(Validate.result(TransactionDict.MS_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MS_FETCH_EXCEPTION)));
					return;
				}

				if (ms != null) {
					sm.setSmNo(Sequence.smSequence());
					sm.setMerNo(transaction.getMerNo());
					sm.setTxnNo(transaction.getTxnNo());
					sm.setSmType(PaymentDict.SM_POUNDAGE);
					sm.setSmAmount(ms.getMsAmount());
					sm.setSmState("1");
					sm.setSmDate(new Date());
					smService.persist(sm);
				}
			}
		}

		jsonResult.put("code", cb.getCbCode());
		jsonResult.put("message", cb.getCbMessage());

		response.getWriter().print(jsonResult.toString());
		return;

	}
}
